import { reactive } from "vue";
import type { Entry, LayEntry } from "@/api/types";
import { BizDict, BizLayDict } from "@/api/index";

import type { DictEntryModel, DictEntryReq } from "@/api/dict-entry/types";
import { dictEntryApi } from "@/api/dict-entry/index";

import type { DictLayEntryModel, DictLayEntryReq } from "@/api/dict-lay-entry/types";
import { dictLayEntryApi } from "@/api/dict-lay-entry/index";

/** 查询缓存字典键值对 */
export async function dictMapCache(typeCode: string, enable?: boolean): Promise<DictEntryModel[]> {
  return new Promise<DictEntryModel[]>((resolve, reject) => {
    const dictKey: string = `dict_${typeCode}_${enable}`;
    let dictStr = sessionStorage.getItem(dictKey);
    if (dictStr) {
      resolve(JSON.parse(dictStr));
    }
    if (!dictStr) {
      if (typeof dictEntryApi.findList == "undefined") {
        console.error("dictTypeApi.findList is not defined.");
        return;
      }
      const req = { typeCode: typeCode, enable: enable } as DictEntryReq;
      dictEntryApi.findList(req).then(({ data }) => {
        const values = data.results as DictEntryModel[];
        dictStr = JSON.stringify(values);
        if (data && data.results != undefined) {
          sessionStorage.setItem(dictKey, dictStr);
        }
        resolve(values);
      });
    }
  });
}

//普通数据字典
export class EntryDict {
  typeCode: string;
  enable?: boolean;
  values: DictEntryModel[];
  constructor(typeCode: string, enable?: boolean) {
    this.typeCode = typeCode;
    this.enable = enable;
    this.values = reactive([]);
    this.useDictValues();
  }

  //加载数据字典.
  useDictValues(): Promise<DictEntryModel[]> {
    return new Promise<DictEntryModel[]>((resolve, reject) => {
      dictMapCache(this.typeCode, this.enable).then((data: DictEntryModel[]) => {
        this.values.length = 0;
        this.values.push(...data);
        resolve(this.values);
      });
    });
  }

  //获取字典值
  getDictValue(key: string): string {
    const entry = this.values.find((entry) => entry.dictCode === key);
    return entry?.dictName ? entry.dictName : "";
  }

  clearCache(): void {
    const dictKey: string = `dict_${this.typeCode}_${this.enable}`;
    sessionStorage.removeItem(dictKey);
  }
}

//层级字典 Code
export class EntryBizLayDict extends BizLayDict {
  // 实现 useValues 方法
  useValues(): Promise<LayEntry[]> {
    return new Promise((resolve, reject) => {
      if (typeof dictLayEntryApi.findList == "undefined") {
        console.error("dictLayEntryApi.findList is not defined.");
        resolve(this.values);
        return;
      }
      const req = { ...this.query } as DictLayEntryReq;
      dictLayEntryApi
        .findList(req)
        .then(({ data }) => {
          const items = data.results as DictLayEntryModel[];
          this.values.length = 0;
          this.values.push(...this.convertToLayEntryArray(items));
          resolve(this.values);
        })
        .catch(reject);
    });
  }

  convertToLayEntryArray(dictLayEntries: DictLayEntryModel[]): LayEntry[] {
    return dictLayEntries.map((dictLayEntry) => {
      return {
        value: dictLayEntry.dictCode,
        label: dictLayEntry.dictName,
        parentId: dictLayEntry.parentId || "",
        children: dictLayEntry.children ? this.convertToLayEntryArray(dictLayEntry.children) : []
      };
    });
  }
}

//层级字典 ID
export class EntryIdBizLayDict extends BizLayDict {
  // 实现 useValues 方法
  useValues(): Promise<LayEntry[]> {
    return new Promise((resolve, reject) => {
      if (typeof dictLayEntryApi.findList == "undefined") {
        console.error("dictLayEntryApi.findList is not defined.");
        resolve(this.values);
        return;
      }
      const req = { ...this.query } as DictLayEntryReq;
      dictLayEntryApi
        .findList(req)
        .then(({ data }) => {
          const items = data.results as DictLayEntryModel[];
          this.values.length = 0;
          this.values.push(...this.convertToLayEntryArray(items));
          resolve(this.values);
        })
        .catch(reject);
    });
  }

  convertToLayEntryArray(dictLayEntries: DictLayEntryModel[]): LayEntry[] {
    return dictLayEntries.map((dictLayEntry) => {
      return {
        value: dictLayEntry.dictId,
        label: dictLayEntry.dictName,
        parentId: dictLayEntry.parentId || "",
        children: dictLayEntry.children ? this.convertToLayEntryArray(dictLayEntry.children) : []
      };
    });
  }
}
